home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / mmdf / mmdf-IIb.43 / uip / other / v6mail.c < prev    next >
Encoding:
C/C++ Source or Header  |  1988-06-02  |  15.8 KB  |  708 lines

  1. #include "util.h"                 /* to get mmdf reply codes            */
  2. #include "mmdf.h"                 /* to get mmdf reply codes            */
  3. #include "cnvtdate.h"
  4. #include <pwd.h>
  5. #include <signal.h>
  6. #include <sys/stat.h>
  7.  
  8. /*  Upgrade to use MMDF Submit; 10 Nov. 1978; David H. Crocker
  9.  *    1 Dec 78 Dave Crocker:  add mail-reading, approx like old "mail"
  10.  *   15 Dec 78 Dave Crocker:  add sndmsg & memo & "-" interfaces
  11.  *   16 Dec 78 Dave Crocker:  "-" not generate return address
  12.  *   25 Apr 80 Dave Crocker:  fix .mail acquisition, default to save
  13.  *   14 Jun 80 Dave Crocker:  turn tty writing off/on
  14.  *   17 Jul 80 Dave Crocker:  fix -c
  15.  *   24 Sep 80 Dave Crocker:  add -r
  16.  *   12 Oct 80 Dave Crocker:  add -g & signature file
  17.  *   15 Nov 80 Dave Crocker:  conversion to V7 package & use of mm_io
  18.  *    1 Dec 80 Dave Crocker:  check success of ALL system calls
  19.  *   20 Jul 81 Dave Crocker:  fix dobody() to detect end from terminal
  20.  *   16 Jul 82 Dave Crocker:  make addresses have '@' only; no " at "
  21.  *    6 Dec 83 Doug Kingston: remove tty write stuff, this is not the place.
  22.  *   19 May 83 Doug Kingston: fix -r to pass a flag to submit
  23.  */
  24.  
  25. long int    curnewpos,
  26.         poshack;              /* keep track of current position     */
  27.                   /*   because ftell isn't on V6        */
  28. FILE *  newfp;                    /* handle on .mail file               */
  29.  
  30. char   *logdir;
  31. char   *username;
  32. char   *mbxname;                  /* full pathname to mailbox           */
  33. char    *binbox;
  34. char    ttyobuf[BUFSIZ];          /* for buffering ttyoutput            */
  35. char    *index();
  36. char    *strdup();
  37. char    *sbmtargs = (char *) 0;
  38. char    *subject = (char *) 0;
  39. char    *replyto = (char *) 0;
  40. char    *sender = (char *) 0;
  41. char    *from = (char *) 0;
  42. char    tolist[LINESIZE];
  43. char    cclist[LINESIZE];
  44.  
  45. /* mmdf globals */
  46.  
  47. extern int sentprotect;           /* default mailbox protection         */
  48. extern char     *mldflfil;        /* default mailbox file               */
  49. extern char     *mldfldir;        /* directory containing mailbox file  */
  50. extern char     *delim1;          /* string delimiting messages         */
  51. extern char     *locname;
  52. extern char     *locdomain;
  53.  
  54. /* end of mmdf globals */
  55.  
  56.  
  57. char    noret;                    /* no return address                  */
  58. char    watchit;                  /* user wants to watch delivery       */
  59. char    idflag;                   /* insert a Message ID header line    */
  60. char    qrychar;                  /* user-specified default save status */
  61.  
  62. char    usertype;
  63. #define U_MAIL  0                 /* the original mail command          */
  64. #define U_SND   1                 /* sndmsg-type prompting              */
  65. #define U_MEMO  2                 /* memo prompting                     */
  66. #define U_LMEM  3                 /* logged in as memo, for memo        */
  67.  
  68. #define FRMNONE 0                 /* no From field specified            */
  69. #define FRMTXT  1                 /* From field had text only           */
  70. #define FRMSNDR 2                 /* field had sender info, too         */
  71.  
  72. char    addrtype;
  73. #define ADDR_TO 0                 /* add addresses to the to list       */
  74. #define ADDR_CC 1                 /* add addresses to the cc list       */
  75.  
  76. /*  **************************  MAIN  ******************************* */
  77.  
  78. main (argc, argv)
  79. int     argc;
  80. char   *argv[];
  81. {
  82.     setbuf (stdout, ttyobuf);
  83.     mmdf_init (argv[0]);
  84.     pgminit ();
  85.  
  86.     if (initstr ("snd", argv[0], 3)
  87.         || strindex ("/snd", argv[0]) != -1
  88.         || initstr ("snd", &argv[0][1], 3)
  89.         || strindex ("sndmsg", argv[0]) != -1)
  90.     usertype = U_SND;
  91.     else
  92.     if (strindex ("memo", argv[0]) != -1)
  93.         usertype = U_MEMO;
  94.     else
  95.         if (argv[0][0] == '-' && argv[0][1] == '\0')
  96.         {                     /* "-" => login shell   */
  97.         usertype = U_LMEM;
  98.         signal (SIGHUP, SIG_IGN);
  99.                   /* renable these for exiting  */
  100.         prompt ("Send a memo\n");
  101.         }
  102.     if (usertype == U_MAIL && (argc == 1 || (argc == 2 && *argv[1] == '-')))
  103.     readmail (argc, argv);    /* only when invoked at "mail"  */
  104.     else
  105.     sendmail (argc, argv);
  106. }
  107. /* */
  108.  
  109. leave (val)
  110. int     val;
  111. {
  112.     if (newfp)
  113.     lk_fclose(newfp, mbxname, (char *)0, (char *)0);
  114.     exit (val == OK ? 0 : 99);
  115. }
  116.  
  117. pipsig ()
  118. {
  119.     if (rp_gval (endchild (NOTOK)) == RP_NO)
  120.     prompt ("Problem accessing mail submission program\n");
  121.                   /* only comment if it looks like      */
  122.                   /*  submit died ugly                  */
  123.     leave (NOTOK);
  124. }
  125.  
  126. pgminit ()
  127. {
  128.     extern struct passwd *getpwuid ();
  129.     extern char *getmailid ();
  130.     struct passwd  *pwdptr;
  131.     int     realid,
  132.         effecid;
  133.  
  134.     signal (SIGPIPE, pipsig);    /* catch write to bad pipe            */
  135.  
  136.     getwho (&realid, &effecid);   /* who am i?                          */
  137.  
  138.     if ((pwdptr = getpwuid (realid)) == (struct passwd *) NULL)
  139.     err_abrt (RP_PARM, "Unable to locate user's name");
  140.  
  141.     /*  save login directory   */
  142.     logdir = strdup(pwdptr -> pw_dir);
  143.  
  144.     if ((username = getmailid(pwdptr -> pw_name)) == NULL)
  145.     err_abrt (RP_PARM, "Unable to locate user's mailid");
  146. }
  147. /* */
  148.  
  149. readmail (argc, argv)
  150. int     argc;
  151. char   *argv[];
  152. {
  153.     register int    count;
  154.  
  155.     if (argc == 2)
  156.     qrychar = argv[1][1];
  157.  
  158.     readinit ();
  159.     for (count = 0; msgstrt () && showmsg () && savmsg (); count++);
  160.     if (count == 0)
  161.     err_abrt (RP_OK, "No new mail");
  162.     endread ();
  163. }
  164.  
  165. readinit ()
  166. {
  167.     extern char *multcat ();
  168.     int     newfd;
  169.     extern int  errno;
  170.  
  171.     mbxname = multcat (
  172.         ((mldfldir == 0 || isnull(*mldfldir)) ? logdir : mldfldir),
  173.          "/",
  174.         ((mldflfil == 0 || isnull(*mldflfil)) ? username : mldflfil),
  175.           0);
  176.     binbox = multcat (
  177.         ((mldfldir == 0 || isnull(*mldfldir)) ? logdir : mldfldir),
  178.          "/._",
  179.         ((mldflfil == 0 || isnull(*mldflfil)) ? username : mldflfil),
  180.           0);
  181.     if (access(binbox, 0) == 0) {
  182.     fprintf(stderr, "Your mailbox has a binary box (%s),\n", binbox);
  183.     fprintf(stderr, "probably created by another mail reading program like MSG.\n");
  184.     fprintf(stderr, "You should remove the binary box before running this program\n");
  185.     fprintf(stderr, "again, or use MSG instead to read your mail.\n");
  186.     exit (99);
  187.     }
  188.  
  189.     if ((newfd = lk_open (mbxname, 0, (char *)0, (char *)0, 5)) == -1)
  190.     err_abrt (RP_OK,
  191.             (errno == ETXTBSY) ? "Mailbox is busy" : "No new mail");
  192.  
  193.     newfp = fdopen (newfd, "r");
  194.     poshack = 0l;
  195. }
  196.  
  197. endread ()
  198. {
  199.     fflush (stdout);
  200.  
  201.     if (creat (mbxname, sentprotect) == NOTOK)
  202.                   /* truncate the file            */
  203.     err_abrt (RP_FCRT, "Unable to reset %s mailbox", mbxname);
  204.     leave (OK);
  205. }
  206. /* */
  207.  
  208. msgstrt ()
  209. {
  210.     char    linebuf[LINESIZE];
  211.  
  212.     FOREVER
  213.     {
  214.     curnewpos = poshack;
  215.     if (fgets (linebuf, sizeof linebuf, newfp) == NULL)
  216.         return (FALSE);
  217.     if (!strequ (linebuf, delim1))
  218.         break;
  219.     poshack += strlen (linebuf);
  220.     }
  221.     fseek (newfp, curnewpos, 0);
  222.     return (TRUE);
  223. }
  224.  
  225. showmsg ()
  226. {
  227.     char    linebuf[LINESIZE];
  228.     register int    lines;
  229.  
  230.     for (lines = 0; fgets (linebuf, sizeof linebuf - 1, newfp) != NULL;)
  231.     {
  232.     poshack += strlen (linebuf);
  233.     if (strequ (linebuf, delim1))
  234.         return (TRUE);
  235.  
  236.     fputs (linebuf, stdout);
  237.     if (lines++ > 4)
  238.     {
  239.         fflush (stdout);
  240.         lines = 0;
  241.     }
  242.     }
  243.     return ((ferror (newfp) || ferror (stdout)) ? FALSE : TRUE);
  244. }
  245. /* */
  246.  
  247. savmsg ()
  248. {
  249.     static  FILE * mboxfp;
  250.     char    linebuf[LINESIZE];
  251.  
  252.     if (!querysav ())
  253.     return (TRUE);
  254.  
  255.     if (mboxfp == NULL)
  256.     {
  257.     if ((mboxfp = fopen ("mbox", "a")) == NULL ||
  258.         chmod ("mbox", sentprotect) == NOTOK)
  259.         err_abrt (RP_FOPN, "Unable to access/create mbox");
  260.     }
  261.  
  262.     poshack = curnewpos;
  263.     for ( fseek (newfp, curnewpos, 0);
  264.         fgets (linebuf, sizeof linebuf - 1, newfp) != NULL;
  265.         fputs (linebuf, mboxfp))
  266.     {
  267.     poshack += strlen (linebuf);
  268.     if (strequ (linebuf, delim1))
  269.         break;
  270.     }
  271.     fputs (delim1, mboxfp);
  272.     fflush (mboxfp);
  273.     return (ferror (newfp) ? FALSE : TRUE);
  274. }
  275.  
  276. querysav ()
  277. {
  278.     register int  respchar;
  279.  
  280.     if (qrychar == 0)
  281.     {
  282.     prompt ("\nSave? ");
  283.     switch (respchar = getchar ())
  284.     {
  285.         case '\n':
  286.         break;
  287.         case '\0':
  288.         exit (-1);
  289.         default:
  290.         while (getchar () != '\n');
  291.     }
  292.     }
  293.     else
  294.     respchar = qrychar;
  295.     if (respchar == 'n' || respchar == 'N')
  296.     return (0);               /* deletion must be explicit            */
  297.     return (1);                   /* default to saving                    */
  298. }
  299. /*  *************************  SENDING ****************************** */
  300.  
  301. static char regargs[] = "rmxto,cc*";
  302.   /* quick NS timeout, return to sender, mail, extract addrs from to & cc  */
  303.  
  304. sendmail (argc, argv)             /* Send a message                     */
  305. int     argc;
  306. char   *argv[];
  307. {
  308.     extern char *sbargs ();
  309.     int     retval;
  310.     char    linebuf[ADDRSIZE];
  311.     char    hadfrom,
  312.         hadto,
  313.         hadcc;
  314.  
  315.     parseargs(argc, argv);
  316.  
  317.     if (rp_isbad (mm_init ()) || rp_isbad (mm_sbinit ()))
  318.     err_abrt (RP_MECH, "Unable to submit mail; please report this error");
  319.  
  320.     strcpy (linebuf, regargs);    /* standard stuff          */
  321.     if (isstr(sbmtargs))
  322.         strcat (linebuf, sbmtargs);   /* extra args for submit   */
  323.  
  324.     if (usertype == U_LMEM)
  325.     strcat (linebuf, "u");    /* do not verify the from field       */
  326.     if (noret)
  327.     strcat (linebuf, "q");    /* quiet, do not return on errors  */
  328.     if (watchit)
  329.     strcat (linebuf, "w");    /* user wants to watch the process     */
  330.  
  331.     if (rp_isbad (mm_winit ((char *) 0, linebuf, (char *) 0)))
  332.     err_abrt (RP_MECH, "problem with submit message initialization");
  333.  
  334.     dodate ();
  335.  
  336.     hadfrom = dofrom ();
  337.  
  338.     dosubject ();
  339.  
  340.     if (hadfrom == FRMTXT && usertype != U_LMEM)
  341.     dosender ("Sender:  ", (char *) 0, TRUE);
  342.                 /* simple address */
  343.     hadto = doto ();
  344.     hadcc = docc ();
  345.  
  346.     if (!hadto && !hadcc && usertype == U_MAIL)
  347.     err_abrt (RP_PARM, "No addressees specified");
  348.  
  349.     doreply ();
  350.  
  351.     doid ();
  352.  
  353.     if (usertype != U_MAIL)
  354.     {
  355.     doprompt ();              /* get headers          */
  356.     prompt ("Text:\n");
  357.     }
  358.     mm_wtxt ("\n", 1);           /* start the body             */
  359.  
  360.  
  361.     dobody ();
  362.     retval = endbody ();
  363.  
  364.     endchild (OK);
  365.  
  366.     if (usertype != U_MAIL && rp_isgood (retval))
  367.     prompt ("Message posted\n");
  368.  
  369.     leave ((rp_isbad (retval)) ? NOTOK : OK);
  370. }
  371. /*   *************  ARGUMENT PARSING FOR SENDMAIL  **************  */
  372.  
  373. parseargs (argc, argv)               
  374. int     argc;
  375. char   *argv[];
  376. {
  377.     register int    i;
  378.  
  379.     tolist[0] = cclist[0] = '\0';
  380.     addrtype = ADDR_TO;
  381.  
  382.     for (i = 1; i < argc; i++)
  383.     {
  384.     switch (argv[i][0])
  385.     {
  386.     default:
  387.         if (addrtype == ADDR_TO) {
  388.         if (!strlen(tolist))
  389.             strcpy (tolist, argv[i]);
  390.         else {
  391.             strcat (tolist, ", ");
  392.             strcat (tolist, argv[i]);
  393.         }
  394.         } else { /* ADDR_CC */
  395.         if (!strlen(cclist))
  396.             strcpy (cclist, argv[i]);
  397.         else {
  398.             strcat (cclist, ", ");
  399.             strcat (cclist, argv[i]);
  400.         }
  401.         }
  402.         break;
  403.     case '-':
  404.         switch (argv[i][1])
  405.         {
  406.         case '-':
  407.             sbmtargs = &(argv[i][2]);
  408.             break;
  409.  
  410.         case 'r':
  411.             noret = TRUE;
  412.             break;
  413.  
  414.         case 'w':
  415.             watchit = TRUE;
  416.             break;
  417.  
  418.         case 'i':
  419.             idflag = TRUE;
  420.             break;
  421.  
  422.         case 's':
  423.             subject = argv[++i];
  424.             break;
  425.  
  426.         case 'a':
  427.             replyto = argv[++i];
  428.             break;
  429.  
  430.         case 'f':
  431.             if ((++i < argc) && !isstr(sender))
  432.                       from = argv[i];
  433.             break;
  434.  
  435.         case 'g':
  436.             if ((++i < argc) && !isstr(from))
  437.                 sender = argv[i];
  438.             break;
  439.  
  440.         case 't':
  441.             addrtype = ADDR_TO;
  442.             break;
  443.  
  444.         case 'c':
  445.             addrtype = ADDR_CC;    
  446.             break;
  447.         }
  448.         break;
  449.     }
  450.     }
  451. }
  452.  
  453. sndhdr (name, contents)
  454. char    *name,
  455.     *contents;
  456. {
  457.     char    linebuf[LINESIZE];
  458.  
  459.     sprintf (linebuf, "%-10s%s\n", name, contents);
  460.     mm_wtxt (linebuf, strlen (linebuf));
  461. }
  462. /* */
  463.  
  464. dodate ()
  465. {
  466.     char    datbuf[64];
  467.  
  468.     cnvtdate (TIMREG, datbuf);    /* rfc733 format date                 */
  469.     sndhdr ("Date:  ", datbuf);
  470. }
  471.  
  472. doid ()
  473. {
  474.     char    linebuf[LINESIZE];
  475.     char    datbuf[64];
  476.  
  477.     if (idflag)
  478.     {
  479.         cnvtdate (TIMCOM, datbuf);
  480.         sprintf (linebuf, "<%s.%d@%s.%s>", datbuf, getpid(),
  481.             locname, locdomain);
  482.         sndhdr ("Message-Id:  ", linebuf);
  483.     }
  484. }
  485.  
  486. dosubject ()
  487. {
  488.     if (isstr(subject))
  489.     sndhdr ("Subject:  ", subject);
  490. }
  491.  
  492. doreply ()
  493. {
  494.     if (isstr(replyto))
  495.     sndhdr ("Reply-To: ", replyto);
  496. }
  497. /* */
  498.  
  499. dofrom ()
  500. {
  501.     static char fldnam[] = "From:  ";
  502.     register int    i;
  503.  
  504.     if (isstr(sender))
  505.     {
  506.         dosender (fldnam, sender, TRUE);
  507.         return (FRMSNDR);
  508.     }
  509.     else if (isstr(from))
  510.     {
  511.         sndhdr (fldnam, from);
  512.         return (FRMTXT);
  513.     }
  514.     else if (usertype != U_LMEM)       /* not memo                     */
  515.     dosender (fldnam, (char *) 0, TRUE);
  516.  
  517.     return (FRMNONE);
  518. }
  519. /* */
  520.  
  521. dosender (cmpnt, name, fancy)
  522. char    cmpnt[],
  523.     name[];
  524. int     fancy;          /* make address fancy? */
  525. {
  526.     FILE   *sigfp;
  527.     char   *ptr,
  528.         linebuf[ADDRSIZE],
  529.         sigtxt[FILNSIZE];     /* where is signature text?           */
  530.     char    gotsig;
  531.  
  532.     gotsig = FALSE;
  533.  
  534.     if (!fancy || name != 0)
  535.     {
  536.     strcpy (sigtxt, name);
  537.     gotsig = TRUE;
  538.     }
  539.     else
  540.     {                             /* user didn't give us a signature    */
  541.     sprintf (linebuf, "%s/.signature", logdir);
  542.  
  543.     if ((sigfp = fopen (linebuf, "r")) != NULL)
  544.     {
  545.         if (fgets (sigtxt, sizeof sigtxt, sigfp) != NULL) {
  546.         char *cp;
  547.  
  548.         if (cp = index(sigtxt, '\n'))
  549.             *cp = '\0';
  550.             if (sigtxt[0])
  551.             gotsig = TRUE;
  552.         }
  553.     }
  554.     }
  555.  
  556.     if (gotsig)                   /* real name + mailbox                */
  557.     {
  558.     for (ptr = locname; *ptr != 0; ptr++)
  559.         *ptr = uptolow (*ptr);      /* Screw locname */
  560.     sprintf (linebuf, "%s <%s@%s>", sigtxt, username, locname);
  561.     }
  562.     else                          /* just the mailbox info              */
  563.     sprintf (linebuf, "%s@%s", username, locname);
  564.  
  565.     sndhdr (cmpnt, linebuf);
  566. }
  567. /* */
  568.  
  569. doto ()
  570. {
  571.  
  572.     if (strlen(tolist) > 0) {
  573.     sndhdr ("To:  ", tolist);
  574.     return (TRUE);
  575.     } else
  576.         return (FALSE);
  577.  
  578. }
  579. /* */
  580.  
  581. docc ()
  582. {
  583.     if (strlen(cclist) > 0) {
  584.     sndhdr ("cc:  ", cclist);
  585.     return (TRUE);
  586.     } else
  587.     return (FALSE);
  588. }
  589. /* */
  590.  
  591. doprompt ()
  592. {
  593.     if (usertype == U_LMEM)       /* "free" memo          */
  594.     cpyprompt ("From:  ");
  595.     cpyprompt ("To:  ");
  596.     if (usertype == U_SND)        /* sndmsg               */
  597.     cpyprompt ("cc:  ");
  598.     cpyprompt ("Subject:  ");
  599. }
  600.  
  601. prompt (str)
  602. char   *str;
  603. {
  604.     printf ("%s", str);
  605.     fflush (stdout);
  606. }
  607.  
  608. cpyprompt (prom)
  609. char    prom[];
  610. {
  611.     prompt (prom);
  612.     copylin (prom);
  613. }
  614.  
  615. copylin (prelim)
  616. char   *prelim;
  617. {
  618.     char    linebuf[LINESIZE];
  619.     register int    morin;
  620.     register int    c;
  621.  
  622.     for (morin = TRUE; morin; sndhdr (prelim, linebuf), prelim = "")
  623.     {
  624.     morin = FALSE;
  625.     if (fgets (linebuf, sizeof linebuf, stdin) == NULL)
  626.         err_abrt (RP_LIO, "Input error");
  627.  
  628.     if (linebuf[0] == '\n')
  629.         return;
  630.  
  631.     c = strlen (linebuf);
  632.     linebuf[c - 1] = '\0';
  633.     if (linebuf[c - 2] == '\\')
  634.     {
  635.         morin = TRUE;
  636.         linebuf[c-- - 2] = '\n';
  637.     }
  638.     }
  639. }
  640. /* */
  641.  
  642. dobody ()
  643. {
  644.     char    buffer[BUFSIZ];
  645.     register int    i;
  646.  
  647.     while (!feof (stdin) && !ferror (stdin) &&
  648.         (i = fread (buffer, sizeof (char), sizeof (buffer), stdin)) > 0)
  649.     if (rp_isbad (i = mm_wtxt (buffer, i)))
  650.         err_abrt (i, "Problem writing body");
  651.  
  652.     if (ferror (stdin))
  653.     err_abrt (RP_FIO, "Problem reading body");
  654. }
  655.  
  656. endbody ()
  657. {
  658.     struct rp_bufstruct thereply;
  659.     int     len;
  660.  
  661.     if (rp_isbad (mm_wtend ()))
  662.     err_abrt (RP_MECH, "problem ending submission");
  663.  
  664.     if (rp_isbad (mm_rrply (&thereply, &len)))
  665.     err_abrt (RP_MECH, "problem getting submission status");
  666.  
  667.     if (rp_isbad (thereply.rp_val))
  668.     err_abrt (thereply.rp_val, "%s", thereply.rp_line);
  669.  
  670.     return (thereply.rp_val);
  671. }
  672.  
  673. doreset ()
  674. {
  675.     exit (NOTOK);
  676. }
  677.  
  678. /*  *********************  UTILITIES  ***************************  */
  679.  
  680. endchild (type)
  681. int     type;
  682. {
  683.     int retval;
  684.  
  685.  
  686.     if (rp_isgood (retval = mm_sbend ()))
  687.     retval = mm_end (type);
  688.  
  689.     return ((retval == NOTOK) ? RP_FIO : (retval >> 8));
  690. }
  691.  
  692. /*VARARGS2*/
  693. err_abrt (code, fmt, b, c, d)     /* terminate the process              */
  694. int     code;                     /* a mmdfrply.h termination code      */
  695. char   *fmt, *b, *c, *d;
  696. {
  697.     if (fmt) {
  698.     printf (fmt, b, c, d);
  699.         putchar ('\n');
  700.     }
  701.     if (code != RP_OK)
  702.     printf ("Message posting aborted\n");
  703.     fflush (stdout);
  704.     endchild (NOTOK);
  705.     leave (code);
  706. }
  707.  
  708.